home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / dbwrend / source / hit.c < prev    next >
Text File  |  1989-04-17  |  11KB  |  387 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *                    Copyright (c) 1987, David B. Wecker               *
  4.  *                            All Rights Reserved                       *
  5.  *                                                                      *
  6.  * This file is part of DBW_Render                                      *
  7.  *                                                                      *
  8.  * DBW_Render is distributed in the hope that it will be useful, but    *
  9.  * WITHOUT ANY WARRANTY. No author or distributor accepts               *
  10.  * responsibility to anyone for the consequences of using it or for     *
  11.  * whether it serves any particular purpose or works at all, unless     *
  12.  * he says so in writing. Refer to the DBW_Render General Public        *
  13.  * License for full details.                                            *
  14.  *                                                                      *
  15.  * Everyone is granted permission to copy, modify and redistribute      *
  16.  * DBW_Render, but only under the conditions described in the           *
  17.  * DBW_Render General Public License. A copy of this license is         *
  18.  * supposed to have been given to you along with DBW_Render so you      *
  19.  * can know your rights and responsibilities. It should be in a file    *
  20.  * named COPYING. Among other things, the copyright notice and this     *
  21.  * notice must be preserved on all copies.                              *
  22.  ************************************************************************
  23.  *                                                                      *
  24.  * Authors:                                                             *
  25.  *        DBW - David B. Wecker                                         *
  26.  *                                                                      *
  27.  * Versions:                                                            *
  28.  *        V1.0 870125 DBW  - First released version                     *
  29.  *                                                                      *
  30.  ************************************************************************/
  31.  
  32. #define MODULE_HIT
  33. #include "ray.h"
  34.  
  35. void findnormal(np,p,n)
  36. node    *np;
  37. vector  p,
  38. n;
  39. {
  40.      vector ripple,fuzzy,bevelx,bevely,bevelz,tmp;
  41.      float t;
  42.      int w,j,it;
  43.  
  44.      switch (np->kind) 
  45.      {
  46.      case SPHERE   :
  47.           SPHERENORMAL(sptr(np)->center,p,n);
  48.           break;
  49.      case TRIANGLE :
  50.           PLANENORMAL(tptr(np)->ve,tptr(np)->vp,n);
  51.           break;
  52.      case QUAD     :
  53.           PLANENORMAL(qptr(np)->ve,qptr(np)->vp,n);
  54.           break;
  55.      case RING     :
  56.           PLANENORMAL(rptr(np)->ve,rptr(np)->vp,n);
  57.           break;
  58.      }
  59.  
  60.      if (np->attr.tex != 0) 
  61.      { /* don't bother checking if there's no texture */
  62.           if (np->attr.tex == 4) 
  63.           { /* fiddle with normal for all ripples */
  64.                for (w = 0; w < numwaves; w++) 
  65.                {
  66.                     calcripple(p,w,ripple);  /* calculate the wave perturbation */
  67.                     vecsum(ripple,n,n);  /* add ripple bend to normal */
  68.                }
  69.                normalize(n);  /* make sure it's a unit vector after all that */
  70.           }
  71.  
  72.           /* fiddle with normal for one ripple */
  73.           else if (np->attr.tex >= 10 && np->attr.tex <= 19) 
  74.           {
  75.                calcripple(p,np->attr.tex - 10,ripple);  /* calc wave perturbation */
  76.                vecsum(ripple,n,n);  /* add ripple bend to normal */
  77.                normalize(n);  /* make sure it's still a unit vector */
  78.           }
  79.  
  80.           /* check for rough pebbly surface */
  81.           else if (np->attr.tex >= 90 && np->attr.tex <= 99) 
  82.           {
  83.                j = np->attr.tex - 90;  /* select the desired pebble finish */
  84.                vecscale(pebble[j].zoom,p,tmp);
  85.                fuzzy[0] = turbulence(tmp);
  86.                vecscale(1.5,tmp,tmp);
  87.                fuzzy[1] = turbulence(tmp);
  88.                vecscale(1.5,tmp,tmp);
  89.                fuzzy[2] = turbulence(tmp);
  90.                if (fuzzy[0] > 0.7)
  91.                     fuzzy[0] = 0.7;
  92.                if (fuzzy[1] > 0.7)
  93.                     fuzzy[1] = 0.7;
  94.                if (fuzzy[2] > 0.7)
  95.                     fuzzy[2] = 0.7;
  96.                if (rnd() < 0.5)
  97.                     fuzzy[0] = -fuzzy[0];
  98.                if (rnd() < 0.5)
  99.                     fuzzy[1] = -fuzzy[1];
  100.                if (rnd() < 0.5)
  101.                     fuzzy[2] = -fuzzy[2];
  102.                vecscale(pebble[j].scale,fuzzy,fuzzy);
  103.                vecsum(n,fuzzy,n);
  104.                normalize(n);
  105.           }
  106.      }
  107.  
  108.      /*---------------------------------------------------------------------*/
  109.      /* Add any general normal perturbations                                */
  110.  
  111.      if (np->attr.fuz > 0.0) 
  112.      {
  113.           /* Perturb the normal randomly to produce fuzzy surfaces */
  114.           fuzzy[0] = rnd();  /* 0..1 */
  115.           fuzzy[1] = rnd();
  116.           fuzzy[2] = rnd();
  117.           if (rnd() < 0.5)
  118.                fuzzy[0] = -fuzzy[0];
  119.           if (rnd() < 0.5)
  120.                fuzzy[1] = -fuzzy[1];
  121.           if (rnd() < 0.5)
  122.                fuzzy[2] = -fuzzy[2];
  123.  
  124.           /* 'fuzzy' is now approximately a random unit vector */
  125.           vecscale(rnd() * np->attr.fuz,fuzzy,fuzzy);
  126.           vecsum(fuzzy,n,n); /* vector addition of fuzz compunent to true normal */
  127.           normalize(n);  /* Make sure it's still a unit vector */
  128.      }
  129. }
  130.  
  131. int hitcylinder(cp,eye,d,p,t)
  132. cylinder *cp;  /* the cylinder      */
  133. vector eye;    /* source ray origin */
  134. vector d;      /* source ray        */
  135. vector p;
  136. float  *t;
  137. {
  138.      float aa,bb,cc,radical,a2,b2,c2,dist1,dist2;
  139.      vector otop,oeye,p1,p2,opoint1,opoint2;
  140.  
  141.      /*
  142.       *   translate bottom of cylinder to 0,0,0
  143.       *   get translated eyepoint and cylinder top
  144.       */
  145.  
  146.      VECSUB(eye,    cp->bottom, oeye);
  147.      VECSUB(cp->top,cp->bottom, otop);  /* ? */
  148.  
  149.  
  150.      a2 = cp->a*cp->a;
  151.      b2 = cp->b*cp->b;
  152.      c2 = cp->c*cp->c;
  153.  
  154.      if (a2 < SMALL) return( FALSE );
  155.      if (b2 < SMALL) return( FALSE );
  156.      if (c2 < SMALL) return( FALSE );
  157.  
  158.  
  159.      aa  = d[0]*d[0] / a2;
  160.      aa += d[2]*d[2] / b2;
  161.      aa -= d[1]*d[1] / c2;
  162.  
  163.      bb  = d[0]*oeye[0] / a2;
  164.      bb += d[2]*oeye[2] / b2;
  165.      bb -= d[1]*oeye[1] / c2;
  166.  
  167.      cc  = oeye[0]*oeye[0] / a2;
  168.      cc += oeye[2]*oeye[2] / b2;
  169.      cc -= oeye[1]*oeye[1] / c2;
  170.  
  171. /*   
  172.  *   descriminate < 0,  ray misses cylinder
  173.  *   descriminate == 0, ray grazes cylinder
  174.  */
  175.  
  176.      if ((radical = (bb*bb) - (4.0*aa*cc)) < 0.0)
  177.           return( FALSE );
  178.  
  179.      radical = sqrt(radical);
  180.  
  181.      aa = 2.0 * aa;
  182.  
  183.      if ( aa < SMALL ) 
  184.           return( FALSE );  
  185.  
  186.      /* the roots of the quadratic */
  187.  
  188.      dist1 = (-bb + radical) / aa;
  189.      dist2 = (-bb - radical) / aa;
  190.  
  191.  
  192.      VECSCALE(dist1,d,p1);
  193.      VECSUM(p1,oeye,p1);
  194.      VECSCALE(dist2,d,p2);
  195.      VECSUM(p2,oeye,p2);
  196.      VECSUB(oeye,p1,opoint1);
  197.      VECSUB(oeye,p2,opoint2);
  198.      dist1 = NORM(opoint1);
  199.      dist2 = NORM(opoint2);
  200.  
  201.      if (dist1 < dist2) 
  202.      { 
  203.           VECCOPY(p1,p); 
  204.           *t = dist1; 
  205.      }
  206.      else
  207.      { 
  208.           VECCOPY(p2,p); 
  209.           *t = dist2; 
  210.      }
  211.  
  212.      return( TRUE );
  213. }
  214.  
  215. int hitsphere(center,radius,eye,d,p,t)
  216. vector  center;     /* where it is  */
  217. vector  eye;        /* where we are */
  218. vector  d;
  219. vector  p;
  220. float   radius;     /* how big it is */
  221. float   *t;
  222. {
  223.      float   r_r,d_r,t2,radical;
  224.      vector  r;
  225.  
  226.      VECSUB(center,eye,r);
  227.      r_r = DOT(r,r);
  228.      d_r = DOT(d,r);
  229.  
  230.      if ((radical = (d_r*d_r) + (radius*radius) - r_r) < 0.0) 
  231.           return( FALSE );
  232.  
  233.      radical = sqrt(radical);
  234.  
  235.      if (d_r < radical) 
  236.      { 
  237.           *t = d_r + radical; 
  238.           t2 = d_r - radical; 
  239.      }
  240.      else
  241.      { 
  242.           *t = d_r - radical; 
  243.           t2 = d_r + radical; 
  244.      }
  245.  
  246.      if (fabs(*t) < SMALL) 
  247.           *t = t2;
  248.  
  249.      if (*t <= 0) 
  250.           return( FALSE );
  251.  
  252.      VECSCALE((*t),d,p);
  253.      VECSUM(p,eye,p);
  254.      return( TRUE );
  255. }
  256.  
  257. int hitplane(p,ve,vp,eye,d,sfs,inter)
  258. vector  p,
  259.   ve,
  260.   vp,
  261.   eye,
  262.   d,
  263.   sfs,
  264.   inter;
  265. {
  266.      vector h;
  267.      float det;
  268.  
  269.      det  = ve[0] * ((vp[1] * d[2]) - (vp[2] * d[1]));
  270.      det -= vp[0] * ((ve[1] * d[2]) - (ve[2] * d[1]));
  271.      det +=  d[0] * ((ve[1] * vp[2])- (ve[2] * vp[1]));
  272.  
  273.      if (det == 0.0)
  274.           return FALSE;
  275.  
  276.      vecsub(eye,p,h);
  277.  
  278.      sfs[2]  = h[0] * ((ve[1] * vp[2]) - (ve[2] * vp[1]));
  279.      sfs[2] -= h[1] * ((ve[0] * vp[2]) - (ve[2] * vp[0]));
  280.      sfs[2] += h[2] * ((ve[0] * vp[1]) - (ve[1] * vp[0]));
  281.      sfs[2] /= det;
  282.      sfs[2]  = -sfs[2];
  283.  
  284.      if (sfs[2] < SMALL)
  285.           return FALSE;
  286.  
  287.      sfs[0]  = h[0] * ((vp[1] * d[2]) - (vp[2] * d[1]));
  288.      sfs[0] -= h[1] * ((vp[0] * d[2]) - (vp[2] * d[0]));
  289.      sfs[0] += h[2] * ((vp[0] * d[1]) - (vp[1] * d[0]));
  290.      sfs[0] /= det;
  291.  
  292.      sfs[1]  = h[0] * ((ve[2] * d[1]) - (ve[1] * d[2]));
  293.      sfs[1] += h[1] * ((ve[0] * d[2]) - (ve[2] * d[0]));
  294.      sfs[1] -= h[2] * ((ve[0] * d[1]) - (ve[1] * d[0]));
  295.      sfs[1] /= det;
  296.  
  297.      VECCOPY(d,inter);
  298.      VECSCALE(sfs[2],inter,inter);
  299.      VECSUM(inter,eye,inter);
  300.  
  301.      return TRUE;
  302. }
  303.  
  304. int hittriangle(tp,eye,d,p,t)
  305. triangle    *tp;
  306. vector      eye,
  307. d,
  308. p;
  309. float       *t;
  310. {
  311.      vector sfs;
  312.      int hit;
  313.  
  314.      hit = hitplane(tp->position,tp->ve,tp->vp,eye,d,sfs,p) &&
  315.        sfs[0] > 0.0  && sfs[1] > 0.0 &&  sfs[0] + sfs[1] <= 1.0;
  316.      *t = sfs[2];
  317.  
  318.      return hit;
  319. }
  320.  
  321. int hitquad(qp,eye,d,p,t)
  322. quad        *qp;
  323. vector      eye,
  324. d,
  325. p;
  326. float       *t;
  327. {
  328.      vector sfs;
  329.      int hit = FALSE;
  330.  
  331.      if (hitplane(qp->position,qp->ve,qp->vp,eye,d,sfs,p))
  332.           hit = sfs[0] > 0.0 && sfs[1] > 0.0 && sfs[0] <= 1.0 && sfs[1] <= 1.0;
  333.      *t = sfs[2];
  334.      return hit;
  335. }
  336.  
  337. int hitring(rp,eye,d,p,t)
  338. ring        *rp;
  339. vector      eye,
  340. d,
  341. p;
  342. float       *t;
  343. {
  344.      vector  sfs;
  345.      float   r;
  346.      int     hit;
  347.  
  348.      hit = hitplane(rp->position,rp->ve,rp->vp,eye,d,sfs,p) &&
  349.        (r = sfs[0] * sfs[0] + sfs[1] * sfs[1]) <= rp->maxrad &&
  350.        r >= rp->minrad;
  351.      *t = sfs[2];
  352.      return( hit );
  353. }
  354.  
  355. void shell(v,v1,v2,n)
  356. float       v[];
  357. vector      v1[];
  358. node        *v2[];
  359. int         n;
  360. {
  361.      int     gap,i,j;
  362.      node    *temp2;
  363.      vector  temp1;
  364.      float   temp;
  365.  
  366.      sorts++;  /* Keep statistics */
  367.      sort_size += n;
  368.  
  369.      for (gap = n/2; gap > 0; gap /=2)
  370.           for (i = gap; i < n; i++)
  371.                for (j = i-gap; j>=0 && v[j] > v[j+gap]; j -= gap) 
  372.                {
  373.                     temp = v[j];
  374.                     v[j] = v[j+gap];
  375.                     v[j+gap] = temp;
  376.  
  377.                     VECCOPY(v1[j],temp1);
  378.                     VECCOPY(v1[j+gap],v1[j]);
  379.                     VECCOPY(temp1,v1[j+gap]);
  380.  
  381.                     temp2 = v2[j];
  382.                     v2[j] = v2[j+gap];
  383.                     v2[j+gap] = temp2;
  384.                }
  385. }
  386.  
  387.